package com.wtwd.campus.utils;

import org.apache.commons.codec.CharEncoding;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.springframework.http.MediaType;

import javax.net.ssl.SSLContext;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author Lxy
 * @Date 2019/10/31 17:11
 * @Description
 */
public class RequestClient {

    private HttpRequestBase request;
    private boolean https = false;

    public RequestClient https(boolean b) {
        https = b;
        return this;
    }

    public String send() throws Exception {
        try (CloseableHttpClient client = createClient();
             CloseableHttpResponse httpResponse = client.execute(request)) {
            HttpEntity entity = httpResponse.getEntity();
            return EntityUtils.toString(entity, CharEncoding.UTF_8);
        }
    }

    public static RequestBuilder createRequest() {
        return new RequestBuilder();
    }

    private CloseableHttpClient createClient() throws Exception {
        CloseableHttpClient client;
        if (https) {
            client = getIgnoreSSLClient();
        } else {
            client = HttpClients.createDefault();
        }
        return client;
    }

    private static CloseableHttpClient getIgnoreSSLClient() throws Exception {
        SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(null, (x509Certificates, s) -> true).build();
        //创建httpClient
        return HttpClients.custom().setSSLContext(sslContext).
                setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
    }

    private RequestClient(HttpRequestBase request) {
        this.request = request;
    }

    public static class RequestBuilder<T extends HttpRequestBase>{
        private HttpRequestBase request;

        public RequestBuilder body(String json) throws UnsupportedEncodingException {
            if (null != request) {
                if (request instanceof HttpPost) {
                    ((HttpPost) request).setEntity(new StringEntity(json));
                }
            }
            return this;
        }

        public RequestBuilder header(Map<String,String> header) {
            Map<String, String> defaultHeader = new HashMap<>();
            defaultHeader.put("content-type", MediaType.APPLICATION_JSON_VALUE);
            defaultHeader.put("charset", CharEncoding.UTF_8);

            if (null != request) {
                defaultHeader.keySet().forEach(key-> request.setHeader(key, defaultHeader.get(key)));
                if(null!=header) header.keySet().forEach(key->defaultHeader.put(key, header.get(key)));
            }
            return this;
        }

        public RequestBuilder get(String url) {
            this.request = new HttpGet(url);
            return this;
        }

        public RequestBuilder post(String url) {
            this.request = new HttpPost(url);
            return this;
        }

        public RequestBuilder method(Class<T> t, String url) throws Exception{
            this.request = getHttpRequest(t, url);
            return this;
        }

        private T getHttpRequest(Class<T> http, String url)
                throws IllegalAccessException, InstantiationException {
            T tt = http.newInstance();
            tt.setURI(URI.create(url));
            return tt;
        }
        private static RequestConfig config(){
            return RequestConfig
                    .custom()
                    .setConnectTimeout(35000)
                    .setConnectionRequestTimeout(35000)
                    .setSocketTimeout(60000)
                    .build();
        }

        public RequestClient build() {
            if (null == request) throw new IllegalArgumentException("Request must be created first...");
            request.setConfig(config());
            return new RequestClient(request);
        }

    }
}
